package org.daochong.web.filter;

import java.io.IOException;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class SecurityParamFilter implements Filter {
	private String[] urls;

	public void init(FilterConfig filterConfig) throws ServletException {
		if (filterConfig.getInitParameter("sqlKeywords") != null) {
			String keywords = filterConfig.getInitParameter("sqlKeywords");
			SecurityParameterUtils.REG_LIST.put("sqlKeywords",
					Pattern.compile("(.*[^a-zA-Z_0-9]{1}(" + keywords + ")|(" + keywords + ")){1}[^a-zA-Z_0-9]{1}.*"));
		}

		if (filterConfig.getInitParameter("functions") != null) {
			String functions = filterConfig.getInitParameter("functions");
			SecurityParameterUtils.REG_LIST.put("sqlFunctions",
					Pattern.compile("(.*[^a-zA-Z_0-9]{1}(" + functions + ")|(" + functions + ")){1}\\s*\\(.*\\).*"));
		}
		if (filterConfig.getInitParameter("trust") != null) {
			urls = filterConfig.getInitParameter("trust").split(",");
		}

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		String uri = req.getRequestURI();
		String ctx = req.getContextPath();
		if (ctx != null && !ctx.equals("") && uri.startsWith(ctx)) {
			uri = uri.substring(ctx.length());
		}
		if (urls != null) {
			for (String u : this.urls) {
				if (pathMatcher(u, uri)) {
					chain.doFilter(request, response);
					return;
				}
			}
		}
		Map<String, String[]> ar = request.getParameterMap();
		for (String key : ar.keySet()) {
			for (String val : ar.get(key)) {
				SecurityParameterUtils.check(key, request.getCharacterEncoding());
				SecurityParameterUtils.check(val, request.getCharacterEncoding());
			}
		}
		
		chain.doFilter(new SecurityParamRequestWarpper(req), response);
	}

	public void destroy() {

	}

	public static boolean pathMatcher(String pattern, String target) {
		try {
			if (pattern.equals(target)) {
				return true;
			}
			String p = "";
			if (pattern.indexOf("**") >= 0) {
				String[] ar = pattern.split("\\*\\*");
				if (ar[0].equals("")) {
					p = ".*";
				} else {
					p = "(" + ar[0].replaceAll("\\.", "\\\\.") + ").*";
				}
				String last = ar[0];
				for (int i = 1; i < ar.length; i++) {
					p += "(" + ((last.length() > 0 && last.charAt(last.length() - 1) == ar[i].charAt(0))
							? ar[i].substring(1) : ar[i]).replaceAll("\\.", "\\\\.").replaceAll("\\*", "[^/\\\\\\\\]*")
							+ ")";
					last = ar[0];
					p += (i < ar.length - 1 ? ".*" : "");
				}
			} else {
				p = pattern.replaceAll("\\.", "\\\\.").replaceAll("\\*", "[^/\\\\\\\\]*");
			}
			return Pattern.matches(p, target);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return false;
	}
}